<?php
/**
 * User: zhenggui5228@126.com
 * Date: 2018/8/11 下午4:52
 */
// 定义类型常量
defined('PROFILING_DB') or define('PROFILING_DB', 1);
defined('PROFILING_CACHE') or define('PROFILING_CACHE', 2);
defined('PROFILING_LOG') or define('PROFILING_LOG', 3);
defined('PROFILING_HTTP') or define('PROFILING_HTTP', 4);
defined('PROFILING_CUSTOMIZED') or define('PROFILING_CUSTOMIZED', 6);
defined('PROFILING_TOTAL') or define('PROFILING_TOTAL', 100);

// 定义时间点常量
defined('PROFILING_START') or define('PROFILING_START', 1);
defined('PROFILING_END') or define('PROFILING_END', 2);

class CiProfiling
{
    // 运行环境,只有在此环境下,才会进行性能剖析
    private $env;
    // 是否输出详细信息
    private $output_detail;
    // 存放db操作相关的数据
    private $db_profiling;
    // 存放缓存操作相关的数据
    private $cache_profiling;
    // 存放日志操作相关的数据
    private $log_profiling;
    // 存放http操作相关的数据
    private $http_profiling;
    // 存放自定义执行区间的数据
    private $customized_profiling;
    // 存放总耗时数据
    private $total_profiling;
    // 是否已输出
    private $outputed;

    private $profiling_types = array(
        PROFILING_DB => 'db_profiling',
        PROFILING_CACHE => 'cache_profiling',
        PROFILING_LOG => 'log_profiling',
        PROFILING_HTTP => 'http_profiling',
        PROFILING_CUSTOMIZED => 'customized_profiling',
        PROFILING_TOTAL => 'total_profiling'
    );

    public function __construct()
    {
        $CI = &get_instance();
        $CI->load->config('profiling');
        $config = $CI->config->item('profiling');

        $this->env = $config['env'];
        $this->output_detail = $config['output_detail'];
        $this->outputed = false;
    }

    // 记录时间点
    public function record($profiling_type, $record_type, $data)
    {
        if (!$this->checkEnv(ENVIRONMENT)) {
            return;
        }
        $data = preg_replace('/\n/', ' ', $data);
        $profiling_type = $this->profiling_types[$profiling_type];
        if (empty($this->$profiling_type)) {
            $this->$profiling_type = array(
                array(
                    'data' => $data,
                    'time' . $record_type => $this->getTime()
                )
            );
            return;
        }

        foreach ($this->$profiling_type as &$item) {
            if ($item['data'] == $data) {
                $item['time' . $record_type] = $this->getTime();
                return;
            }
        }
        $this->$profiling_type = array_merge(
            $this->$profiling_type,
            array(
                array(
                    'data' => $data,
                    'time' . $record_type => $this->getTime()
                )
            )
        );
    }

    // 检查运行环境
    private function checkEnv($env)
    {
        return $this->env == $env;
    }

    // 剖析运算,得出结果
    public function calculate()
    {
        if (!$this->checkEnv(ENVIRONMENT)) {
            return;
        }

        foreach ($this->profiling_types as $profiling_type) {
            if (!empty($this->$profiling_type)) {
                foreach ($this->$profiling_type as &$item) {
                    if (empty($item['time1']) || empty($item['time2'])) {
                        $CI = &get_instance();
                        $CI->logger->write_log('error', 'profiling time error');
                        continue;
                    } else {
                        $item['time'] = round(($item['time2'] - $item['time1']), 2);
                        unset($item['time1']);
                        unset($item['time2']);
                    }
                }
            }
        }
    }

    // 将性能剖析结果放入header
    public function setHeader()
    {
        if (!$this->checkEnv(ENVIRONMENT) || $this->outputed) {
            return;
        }
        $this->calculate();
        $this->outputed = true;
        header('CI-Profiling:' . json_encode(array(
                'db' => $this->db_profiling,
                'cache' => $this->cache_profiling,
                'log' => $this->log_profiling,
                'http' => $this->http_profiling,
                'total' => $this->total_profiling,
                'customized' => $this->customized_profiling,
                'url' => $_SERVER['REQUEST_URI']
            )));
    }

    // 获取当前时间(毫秒)
    private function getTime()
    {
        return floatval(microtime(true) * 1000);
    }
}

